package com.firefly.admin.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.firefly.admin.common.constant.Constants;
import com.firefly.admin.common.enums.ResultCodeEnum;
import com.firefly.admin.common.exception.BusinessException;
import com.firefly.admin.common.utils.DateUtil;
import com.firefly.admin.common.utils.JwtTokenUtil;
import com.firefly.admin.common.vo.Result;
import com.firefly.admin.system.entity.FySystemNotice;
import com.firefly.admin.system.entity.FySystemOrganization;
import com.firefly.admin.system.entity.FySystemUser;
import com.firefly.admin.system.entity.FySystemUserNotice;
import com.firefly.admin.system.mapper.FySystemNoticeMapper;
import com.firefly.admin.system.service.FySystemNoticeService;
import com.firefly.admin.system.service.FySystemOrganizationService;
import com.firefly.admin.system.service.FySystemUserNoticeService;
import com.firefly.admin.system.service.FySystemUserService;
import com.firefly.admin.system.vo.SelectOption;
import com.firefly.admin.system.vo.SystemNoticeQueryVo;
import com.firefly.admin.system.vo.SystemNoticeStatusUpdateVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FySystemNoticeServiceImpl implements FySystemNoticeService {

    /**
     * 优先级 普通级
     */
    private static final String PRIORITY_LEVEL_ORDINARY = "1";
    private static final String PRIORITY_LEVEL_PARTICULARLY_URGENT = "3";

    @Autowired
    private FySystemNoticeMapper fySystemNoticeMapper;
    @Autowired
    private FySystemUserNoticeService fySystemUserNoticeService;
    @Autowired
    private FySystemUserService fySystemUserService;
    @Autowired
    private FySystemOrganizationService fySystemOrganizationService;

    /**
     * 分页查询系统通知接口
     *
     * @param systemNoticeQueryVo 系统通知查询条件
     * @return 系统通知信息列表
     */
    @Override
    public Result<Page<FySystemNotice>> getSystemNoticeList(SystemNoticeQueryVo systemNoticeQueryVo) {
        log.info("###########FySystemNoticeServiceImpl getSystemNoticeList param = {}", JSONObject.toJSONString(systemNoticeQueryVo));
        LambdaQueryWrapper<FySystemNotice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(systemNoticeQueryVo.getNoticeTitle()), FySystemNotice::getNoticeTitle, systemNoticeQueryVo.getNoticeTitle());
        queryWrapper.eq(StringUtils.isNotBlank(systemNoticeQueryVo.getNoticeType()), FySystemNotice::getNoticeType, systemNoticeQueryVo.getNoticeType());
        queryWrapper.eq(StringUtils.isNotBlank(systemNoticeQueryVo.getPriorityLevel()), FySystemNotice::getPriorityLevel, systemNoticeQueryVo.getPriorityLevel());
        queryWrapper.eq(StringUtils.isNotBlank(systemNoticeQueryVo.getNoticeObjectType()), FySystemNotice::getNoticeObjectType, systemNoticeQueryVo.getNoticeObjectType());
        queryWrapper.eq(StringUtils.isNotBlank(systemNoticeQueryVo.getNoticeStatus()), FySystemNotice::getNoticeStatus, systemNoticeQueryVo.getNoticeStatus());
        queryWrapper.eq(FySystemNotice::getDeleteFlag, Constants.DeleteFlag.NORMAL);
        queryWrapper.orderByDesc(FySystemNotice::getCreateTime);
        Page<FySystemNotice> page = new Page<>(systemNoticeQueryVo.getPage(), systemNoticeQueryVo.getLimit());
        Page<FySystemNotice> systemNoticePage = fySystemNoticeMapper.selectPage(page, queryWrapper);
        List<FySystemNotice> records = systemNoticePage.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            records.forEach(fySystemNotice -> {
                FySystemUser fySystemUser = fySystemUserService.findUserById(fySystemNotice.getReleaseUserId());
                fySystemNotice.setReleaseUser(fySystemUser);
                String noticeObjectType = fySystemNotice.getNoticeObjectType();
                List<FySystemUserNotice> systemUserNoticeList = fySystemUserNoticeService.findListByNoticeId(fySystemNotice.getNoticeId());
                if (!CollectionUtils.isEmpty(systemUserNoticeList)) {
                    List<Long> userIds = systemUserNoticeList.stream().map(FySystemUserNotice::getUserId).collect(Collectors.toList());
                    if (Constants.NoticeObjectType.ORG.equals(noticeObjectType)) {
                        List<FySystemUser> fySystemUserList = fySystemUserService.findUserByIds(userIds);
                        if (!CollectionUtils.isEmpty(fySystemUserList)) {
                            Set<Long> orgIds = fySystemUserList.stream().map(FySystemUser::getOrgId).collect(Collectors.toSet());
                            fySystemNotice.setNoticeObjectIds(new ArrayList<>(orgIds));
                        }
                    } else if (Constants.NoticeObjectType.USER.equals(noticeObjectType)) {
                        fySystemNotice.setNoticeObjectIds(userIds);
                    }
                }
            });
        }
        return Result.success(systemNoticePage);
    }

    /**
     * 查询已发布最新的系统公告接口
     *
     * @return 系统通知信息列表
     */
    @Override
    public Result<FySystemNotice> getLastSystemNotice() {
        List<FySystemNotice> fySystemNoticeList = fySystemNoticeMapper.findUserAlreadyUnreadSystemNoticeOne(JwtTokenUtil.getLoginUserId());
        if (CollectionUtils.isEmpty(fySystemNoticeList)) {
            return Result.success();
        }
        return Result.success(fySystemNoticeList.get(0));
    }

    /**
     * 查询已发布最新5条公告接口
     *
     * @return 系统通知信息列表
     */
    @Override
    public Result<Map<String, List<FySystemNotice>>> getNoticeTop5List() {
        Map<String, List<FySystemNotice>> resultMap = new HashMap<>();
        List<FySystemNotice> systemNoticeList = fySystemNoticeMapper.selectListByType(Constants.NoticeType.SYSTEM_NOTICE, JwtTokenUtil.getLoginUserId(), 5);
        if (!CollectionUtils.isEmpty(systemNoticeList)) {
            for (FySystemNotice fySystemNotice : systemNoticeList) {
                assembleNoticeOtherInfo(fySystemNotice);
            }
        }
        resultMap.put("systemNoticeList", systemNoticeList);
        List<FySystemNotice> userNoticeList = fySystemNoticeMapper.selectListByType(Constants.NoticeType.USER_NOTICE, JwtTokenUtil.getLoginUserId(), 5);
        if (!CollectionUtils.isEmpty(userNoticeList)) {
            for (FySystemNotice fySystemNotice : userNoticeList) {
                assembleNoticeOtherInfo(fySystemNotice);
            }
        }
        resultMap.put("userNoticeList", userNoticeList);
        return Result.success(resultMap);
    }

    /**
     * 组装公告其他信息
     *
     * @param fySystemNotice 公告
     */
    private void assembleNoticeOtherInfo(FySystemNotice fySystemNotice) {
        Long releaseUserId = fySystemNotice.getReleaseUserId();
        FySystemUser fySystemUser = fySystemUserService.findUserById(releaseUserId);
        fySystemNotice.setReleaseUser(fySystemUser);
    }

    /**
     * 查询公告条数接口
     *
     * @return 条数
     */
    @Override
    public Result<Integer> getUnReadNoticeCount() {
        int unReadCount = fySystemUserNoticeService.getUnReadNoticeCount();
        return Result.success(unReadCount);
    }

    /**
     * 系统用户通知已读接口
     *
     * @param noticeId 消息ID
     * @return 操作结果
     */
    @Override
    public Result<FySystemUserNotice> alreadyRead(Long noticeId) {
        if (noticeId == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_USER_MESSAGE_ID_NOT_NULL);
        }
        FySystemUserNotice fySystemUserNoticeResult = fySystemUserNoticeService.alreadyRead(noticeId);
        return Result.success(fySystemUserNoticeResult);
    }

    /**
     * 查询用户通知公告列表接口
     *
     * @param noticeType 通知公告类型
     * @return 系统通知信息列表
     */
    @Override
    public Result<List<FySystemNotice>> getNoticeList(String noticeType) {
        List<FySystemNotice> noticeList = fySystemNoticeMapper.selectListByType(noticeType, JwtTokenUtil.getLoginUserId(), null);
        if (!CollectionUtils.isEmpty(noticeList)) {
            for (FySystemNotice fySystemNotice : noticeList) {
                assembleNoticeOtherInfo(fySystemNotice);
            }
        }
        return Result.success(noticeList);
    }

    /**
     * 查询公告可通知对象列表
     *
     * @param noticeObjectType 公告通知对象类型
     * @return 可通知对象列表
     */
    @Override
    public Result<List<SelectOption>> getNoticeObjectSelectList(String noticeObjectType) {
        List<SelectOption> selectOptionList = new ArrayList<>();
        if (Constants.NoticeObjectType.ALL.equals(noticeObjectType)) {
            return Result.success(selectOptionList);
        } else if (Constants.NoticeObjectType.ORG.equals(noticeObjectType)) {
            List<FySystemOrganization> allUsableOrg = fySystemOrganizationService.getAllUsableOrg();
            if (!CollectionUtils.isEmpty(allUsableOrg)) {
                allUsableOrg.forEach(organization -> {
                    SelectOption selectOption = new SelectOption();
                    selectOption.setValue(organization.getOrgId());
                    selectOption.setLabel(organization.getOrgName());
                    selectOptionList.add(selectOption);
                });
            }
        } else {
            List<FySystemUser> allUsableUser = fySystemUserService.getAllUsableUser();
            if (!CollectionUtils.isEmpty(allUsableUser)) {
                allUsableUser.forEach(fySystemUser -> {
                    SelectOption selectOption = new SelectOption();
                    selectOption.setValue(fySystemUser.getUserId());
                    selectOption.setLabel(fySystemUser.getRealName());
                    selectOptionList.add(selectOption);
                });
            }
        }
        return Result.success(selectOptionList);
    }

    /**
     * 根据公告ID查询公告通知对象列表
     *
     * @param noticeId 公告ID
     * @return 可通知对象列表
     */
    @Override
    public Result<List<FySystemUser>> getNoticeObjectList(Long noticeId) {
        FySystemNotice fySystemNotice = fySystemNoticeMapper.selectById(noticeId);
        if (fySystemNotice == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_NOT_FOUND);
        }
        List<FySystemUser> fySystemUserList = new ArrayList<>();
        List<FySystemUserNotice> systemUserNoticeList = fySystemUserNoticeService.findListByNoticeId(noticeId);
        if (!CollectionUtils.isEmpty(systemUserNoticeList)) {
            List<Long> userIds = systemUserNoticeList.stream().map(FySystemUserNotice::getUserId).collect(Collectors.toList());
            fySystemUserList = fySystemUserService.findUserByIds(userIds);
        }
        return Result.success(fySystemUserList);
    }

    /**
     * 获取系统通知信息接口
     *
     * @param noticeId 系统通知ID
     * @return 系统通知信息
     */
    @Override
    public Result<FySystemNotice> getSystemNotice(Long noticeId) {
        FySystemNotice fySystemNotice = fySystemNoticeMapper.selectById(noticeId);
        if (fySystemNotice == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_NOT_FOUND);
        }
        return Result.success(fySystemNotice);
    }

    /**
     * 系统通知信息新增接口
     *
     * @param fySystemNotice 系统通知信息
     * @return 新增结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<FySystemNotice> add(FySystemNotice fySystemNotice) {
        if (fySystemNotice == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        ResultCodeEnum resultCodeEnum = checkNoticeParam(fySystemNotice);
        if (resultCodeEnum != null) {
            return Result.getResult(resultCodeEnum);
        }
        int rows = fySystemNoticeMapper.insert(fySystemNotice);
        if (rows <= 0) {
            return Result.getResult(ResultCodeEnum.ADD_EXCEPTION);
        }
        releaseNoticeToUser(fySystemNotice);
        return Result.success(fySystemNotice);
    }

    /**
     * 系统通知信息编辑接口
     *
     * @param fySystemNotice 系统通知信息
     * @return 编辑结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<FySystemNotice> update(FySystemNotice fySystemNotice) {
        if (fySystemNotice == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        Long noticeId = fySystemNotice.getNoticeId();
        if (noticeId == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        FySystemNotice systemNotice = fySystemNoticeMapper.selectById(noticeId);
        if (systemNotice == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_NOT_FOUND);
        }
        ResultCodeEnum resultCodeEnum = checkNoticeParam(fySystemNotice);
        if (resultCodeEnum != null) {
            return Result.getResult(resultCodeEnum);
        }
        fySystemUserNoticeService.deleteByNoticeId(noticeId);
        releaseNoticeToUser(fySystemNotice);
        int rows = fySystemNoticeMapper.updateById(fySystemNotice);
        if (rows <= 0) {
            return Result.getResult(ResultCodeEnum.ADD_EXCEPTION);
        }
        return Result.success(fySystemNotice);
    }

    public void releaseNoticeToUser(FySystemNotice fySystemNotice) {
        fySystemNotice.setReleaseTime(DateUtil.getNowDate());
        fySystemNotice.setReleaseUserId(JwtTokenUtil.getLoginUserId());
        String noticeObjectType = fySystemNotice.getNoticeObjectType();
        List<Long> noticeObjectIds = fySystemNotice.getNoticeObjectIds();
        List<Long> userIds = new ArrayList<>();
        if (Constants.NoticeObjectType.ALL.equals(noticeObjectType)) {
            //推送给所有人
            List<FySystemUser> fySystemUserList = fySystemUserService.getAllUsableUser();
            if (!CollectionUtils.isEmpty(fySystemUserList)) {
                userIds = fySystemUserList.stream().map(FySystemUser::getUserId).collect(Collectors.toList());
            }
        } else if (Constants.NoticeObjectType.ORG.equals(noticeObjectType)) {
            if (!CollectionUtils.isEmpty(noticeObjectIds)) {
                //推送给一些组织机构
                List<FySystemUser> fySystemUserList = fySystemUserService.findUserByOrgIds(new HashSet<>(noticeObjectIds));
                if (!CollectionUtils.isEmpty(fySystemUserList)) {
                    userIds = fySystemUserList.stream().map(FySystemUser::getUserId).collect(Collectors.toList());
                }
            }
        } else if (Constants.NoticeObjectType.USER.equals(noticeObjectType)) {
            //推送给一些用户
            userIds = noticeObjectIds;
        }
        for (Long userId : userIds) {
            fySystemUserNoticeService.save(userId, fySystemNotice.getNoticeId(), fySystemNotice.getNoticeType());
        }
    }

    /**
     * 校验公告参数
     *
     * @param fySystemNotice 公告信息
     * @return 校验结果
     */
    public ResultCodeEnum checkNoticeParam(FySystemNotice fySystemNotice) {
        String noticeTitle = fySystemNotice.getNoticeTitle();
        if (StringUtils.isBlank(noticeTitle)) {
            throw new BusinessException("公告标题不能为空");
        }
        String noticeType = fySystemNotice.getNoticeType();
        if (StringUtils.isBlank(noticeType)) {
            fySystemNotice.setNoticeType(Constants.NoticeType.USER_NOTICE);
        }
        String noticeStatus = fySystemNotice.getNoticeStatus();
        if (StringUtils.isBlank(noticeStatus)) {
            fySystemNotice.setNoticeStatus(Constants.NoticeStatus.UNRELEASED);
        }
        if (Constants.NoticeType.SYSTEM_NOTICE.equals(noticeType)) {
            fySystemNotice.setNoticeObjectType(Constants.NoticeObjectType.ALL);
        } else {
            fySystemNotice.setPriorityLevel(PRIORITY_LEVEL_ORDINARY);
        }
        return null;
    }

    /**
     * 系统通知状态修改接口
     *
     * @param systemNoticeStatusUpdateVo 系统通知状态编辑参数
     * @return 操作结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<FySystemNotice> updateStatus(SystemNoticeStatusUpdateVo systemNoticeStatusUpdateVo) {
        if (systemNoticeStatusUpdateVo == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        Long noticeId = systemNoticeStatusUpdateVo.getNoticeId();
        if (noticeId == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        FySystemNotice systemNotice = fySystemNoticeMapper.selectById(noticeId);
        if (systemNotice == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_NOT_FOUND);
        }
        String noticeStatus = systemNoticeStatusUpdateVo.getNoticeStatus();
        if (StringUtils.isBlank(noticeStatus)) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_STATUS_NOT_NULL);
        }
        if (Constants.NoticeStatus.RELEASE.equals(noticeStatus)) {
            systemNotice.setReleaseTime(DateUtil.getNowDate());
            systemNotice.setReleaseUserId(JwtTokenUtil.getLoginUserId());
        }
        systemNotice.setNoticeStatus(noticeStatus);
        int rows = fySystemNoticeMapper.updateById(systemNotice);
        if (rows <= 0) {
            return Result.getResult(ResultCodeEnum.ADD_EXCEPTION);
        }
        return Result.success(systemNotice);
    }

    /**
     * 系统通知信息删除接口
     *
     * @param noticeId 通知ID
     * @return 删除结果
     */
    @Override
    public Result<String> delete(Long noticeId) {
        if (noticeId == null) {
            return Result.getResult(ResultCodeEnum.REQUEST_PARAM_EXCEPTION);
        }
        FySystemNotice systemNotice = fySystemNoticeMapper.selectById(noticeId);
        if (systemNotice == null) {
            return Result.getResult(ResultCodeEnum.SYSTEM_NOTICE_NOT_FOUND);
        }
        systemNotice.setDeleteFlag(Constants.DeleteFlag.DELETE);
        int rows = fySystemNoticeMapper.updateById(systemNotice);
        if (rows <= 0) {
            return Result.getResult(ResultCodeEnum.ADD_EXCEPTION);
        }
        return Result.success();
    }
}
